import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';

import { CreateAuthorityDTO } from './dto/create-authority.dto';
import { prisma } from '../../generated/prisma-client/sys';
import { UserInputError } from 'apollo-server';
import { UpdateAuthorityDTO } from './dto/update-authority.dto';
import { Authorities } from 'src/common/decorator/authorities.decorator';

@Resolver('SysAuthority')
export class SysAuthorityResolver {
  @Query('querySysAuthorities')
  @Authorities('AUTH_SYS_AUTHORITY_VIEW')
  async querySysAuthorities() {
    const fragment = `
      fragment SysAuthorityTable on SysAuthority {
        id
        name
        description
        level
        type
        path
        isSystem
        dateCreated
        dateUpdated
        children {
          id
          name
          description
          level
          type
          path
          isSystem
          dateCreated
          dateUpdated
          parent {
            id
            name
            path
            description
          }
          children {
            id
            name
            description
            level
            type
            path
            isSystem
            dateCreated
            dateUpdated
            parent {
              id
              name
              path
              description
            }
          }
        }
      }
    `;
    return await prisma
      .sysAuthorities({ where: { level: 1 } })
      .$fragment(fragment);
  }

  @Query('sysAuthorities')
  @Authorities('AUTH_SYS_ROLE_CREATE', 'AUTH_SYS_ROLE_UPDATE')
  async sysAuthorities() {
    const fragment = `
      fragment AuthoritiesSelect on SysAuthority {
        id
        description
        children {
          id
          description
          children {
            id
            description
          }
        }
      }
    `;
    return await prisma
      .sysAuthorities({ where: { level: 1 } })
      .$fragment(fragment);
  }

  @Query('sysMenu')
  async sysMenu() {
    const fragment = `
      fragment SysMenu on SysAuthority {
        name
        description
        path
        children(where: { type: "MENU" }) {
          name
          description
          path
        }
      }
    `;
    return await prisma
      .sysAuthorities({ where: { level: 1 } })
      .$fragment(fragment);
  }

  @Query('sysAuthority')
  async sysAuthority(
    @Args('id')
    id: string,
  ) {
    return prisma.sysAuthority({ id });
  }

  @Mutation('createSysAuthority')
  @Authorities('AUTH_SYS_AUTHORITY_CREATE')
  async createSysAuthority(
    @Args('authority')
    { parentId, ...data }: CreateAuthorityDTO,
  ) {
    const tmp = await prisma.sysAuthority({ name: data.name });
    if (tmp) {
      throw new UserInputError('权限已存在！', { property: 'name' });
    }

    // get admin role
    const admin = await prisma.sysRole({ name: 'ROLE_ADMIN' });

    // don't save menu nodes for admin role
    const isMenu = data.type === 'MENU';

    return await prisma.createSysAuthority({
      ...data,
      parent: {
        connect: parentId && { id: parentId },
      },
      roles: {
        connect: !isMenu ? admin && { id: admin.id } : null,
      },
    });
  }

  @Mutation('updateSysAuthority')
  @Authorities('AUTH_SYS_AUTHORITY_UPDATE')
  async updateSysAuthority(
    @Args('authority')
    { id, ...data }: UpdateAuthorityDTO,
  ) {
    return await prisma.updateSysAuthority({
      where: { id },
      data: {
        ...data,
      },
    });
  }

  @Mutation('deleteSysAuthority')
  @Authorities('AUTH_SYS_AUTHORITY_DELETE')
  async deleteSysAuthority(
    @Args('id')
    id: string,
  ) {
    return await prisma.deleteSysAuthority({ id });
  }
}
